package cs241.lab.world.DblLinkList;

/** Doubly linked list with nodes of type DNode storing strings. */
public class Dlist {
  protected int size;			// number of elements
  protected Node header, trailer;	// sentinels
  /** Constructor that creates an empty list */
  public Dlist() { 
    size = 0;
    header = new Node(null, null, null);	// create header
    trailer = new Node(null, header, null);	// create trailer
    header.setNext(trailer);	// make header and trailer point to each other
  }
  /** Returns the number of elements in the list */
  public int size() { return size; }
  /** Returns whether the list is empty */
  public boolean isEmpty() { return (size == 0); }
  /** Returns the first node of the list */
  public Node getFirst() throws IllegalStateException {
    if (isEmpty()) throw new IllegalStateException("List is empty");
    return header.getNext();
  }
  /** Returns the last node of the list */
  public Node getLast() throws IllegalStateException {
    if (isEmpty()) throw new IllegalStateException("List is empty");
    return trailer.getPrevious();
  }
  /** Returns the node before the given node v. An error occurs if v
    * is the header */
  public Node getPrev(Node v) throws IllegalArgumentException {
    if (v == header) throw new IllegalArgumentException
      ("Cannot move back past the header of the list");
    return v.getPrevious();
  }
  /** Returns the node after the given node v. An error occurs if v
    * is the trailer */
  public Node getNext(Node v) throws IllegalArgumentException {
    if (v == trailer) throw new IllegalArgumentException
      ("Cannot move forward past the trailer of the list");
   return v.getNext();
  }
  
  /** Inserts the given node z before the given node v. An error
   * occurs if v is the header */
 public void addBefore(Node v, Node z) throws IllegalArgumentException {
   Node u = getPrev(v);	// may throw an IllegalArgumentException
   z.setPrevious(u);
   z.setNext(v);
   v.setPrevious(z);
   u.setNext(z);
   size++;
 }
 /** Inserts the given node z after the given node v. An error occurs
   * if v is the trailer */
 public void addAfter(Node v, Node z) {
   Node w = getNext(v);	// may throw an IllegalArgumentException
   z.setPrevious(v);
   z.setNext(w);
   w.setPrevious(z);
   v.setNext(z);
   size++;
 }
 /** Inserts the given node at the head of the list */
 public void addFirst(Node v) {
   addAfter(header, v);
 }
 /** Inserts the given node at the tail of the list */
 public void addLast(Node v) {
   addBefore(trailer, v);
 }
 /** Removes the given node v from the list. An error occurs if v is
   * the header or trailer */
 public void remove(Node v) {
   Node u = getPrev(v);	// may throw an IllegalArgumentException
   Node w = getNext(v);	// may throw an IllegalArgumentException
   // unlink the node from the list 
   w.setPrevious(u);
   u.setNext(w);
   v.setPrevious(null);
   v.setNext(null);
   size--;
 }

}
